package com.basker.pisces.core.repository;

import java.util.Collection;

import com.basker.pisces.core.exception.StaleObjectException;
import com.basker.pisces.core.query.builder.CriterionBuilder;
import com.basker.pisces.spring.SpringApplicationContext;

/**
 * 用于访问javabean业务对象的数据仓库接口
 *
 * @author hangwen
 * @version 1.0
 * @since 1.0
 */
public interface IBeanRepository {

    /**
     * 获取IBeanRepository的实例
     *
     * @return
     */
    public static IBeanRepository getInstance() {
        return SpringApplicationContext.getInstance().getBean(IBeanRepository.class);
    }

    /**
     * 通过id删除一个javabean
     *
     * @param id
     */
    <TBean> void deleteBean(Class<TBean> clazz, Object id);

    /**
     * 通过id批量删除javabean
     *
     * @param clazz
     * @param id
     */
    <TBean> void deleteBeans(Class<TBean> clazz, Object[] ids);

    /**
     * 填充外键字段的值
     *
     * @param objectMeta  对象元信息
     * @param dataObjects 待填充的对象
     */
    <TBean> void fillRefrenceFields(Class<TBean> clazz, TBean[] dataObjects);

    /**
     * 通过id加载指定的javabean
     *
     * @param clazz javabean的class
     * @param id    主键值
     * @return
     */
    <TBean> TBean loadBean(Class<TBean> clazz, Object id);

    /**
     * 通过id加载指定的javabean,用于修改更新
     *
     * @param clazz javabean的class
     * @param id    主键值
     * @return
     */
    <TBean> TBean loadBeanForUpdate(Class<TBean> clazz, Object id);

    /**
     * 通过id批量加载指定的javabean
     *
     * @param clazz javabean的class
     * @param ids   主键值
     * @return
     */
    <TBean> TBean[] loadBeans(Class<TBean> clazz, Object[] ids);

    /**
     * 通过id批量加载指定的javabean,用于修改更新
     *
     * @param clazz javabean的class
     * @param ids   主键值
     * @return
     */
    <TBean> TBean[] loadBeansForUpdate(Class<TBean> clazz, Object[] ids);

    /**
     * 通过id加载指定的javabean
     *
     * @param clazz      javabean的class
     * @param loadFields 需要加载的字段集合,如果为空，默认加载Id、代码和名称字段
     * @param id         主键值
     * @return
     */
    <TBean> TBean loadPartBean(Class<TBean> clazz, Collection<String> loadFields, Object id);

    /**
     * 通过id加载指定的javabean,用于修改更新
     *
     * @param clazz      javabean的class
     * @param loadFields 需要加载的字段集合,如果为空，默认加载Id、代码和名称字段
     * @param id         主键值
     * @return
     */
    <TBean> TBean loadPartBeanForUpdate(Class<TBean> clazz, Collection<String> loadFields, Object id);

    /**
     * 通过id批量加载指定的javabean
     *
     * @param clazz      javabean的class
     * @param loadFields 需要加载的字段集合,如果为空，默认加载Id、代码和名称字段
     * @param ids主键值
     * @return
     */
    <TBean> TBean[] loadPartBeans(Class<TBean> clazz, Collection<String> loadFields, Object[] ids);

    /**
     * 通过id批量加载指定的javabean,用于修改更新
     *
     * @param clazz      javabean的class
     * @param loadFields 需要加载的字段集合,如果为空，默认加载Id、代码和名称字段
     * @param ids主键值
     * @return
     */
    <TBean> TBean[] loadPartBeansForUpdate(Class<TBean> clazz, Collection<String> loadFields, Object[] ids);

    /**
     * 通过CriteriaBuilder组装条件，并查询单个javabean
     *
     * @param clazz    javabean的class
     * @param builders 条件构建器
     * @return
     */
    <TBean> TBean queryBean(Class<TBean> clazz, CriterionBuilder... builders);

    /**
     * 通过sql条件加载指定的单个javabean
     *
     * @param clazz    javabean的class
     * @param whereSql 条件sql,参数用?
     * @param args     参数
     * @return
     */
    <TBean> TBean queryBean(Class<TBean> clazz, String whereSql, Object... args);

    /**
     * 通过CriteriaBuilder组装条件，并查询单个javabean,用于修改更新
     *
     * @param clazz    javabean的class
     * @param builders 条件构建器
     * @return
     * @see CriterionBuilder
     */
    <TBean> TBean queryBeanForUpdate(Class<TBean> clazz, CriterionBuilder... builders);

    /**
     * 通过sql条件加载指定的单个javabean,用于修改更新
     *
     * @param clazz    javabean的class
     * @param whereSql 条件sql,参数用?
     * @param args     参数
     * @return
     */
    <TBean> TBean queryBeanForUpdate(Class<TBean> clazz, String whereSql, Object... args);

    /**
     * 通过CriteriaBuilder组装条件，并查询javabean
     *
     * @param clazz    javabean的class
     * @param builders 条件构建器
     * @return
     * @see CriterionBuilder
     */
    <TBean> TBean[] queryBeans(Class<TBean> clazz, CriterionBuilder... builders);

    /**
     * 通过sql条件加载指定的javabean
     *
     * @param clazz    javabean的class
     * @param whereSql 条件sql,参数用?
     * @param args     参数
     * @return
     */
    <TBean> TBean[] queryBeans(Class<TBean> clazz, String whereSql, Object... args);

    /**
     * 通过CriteriaBuilder组装条件，并查询javabean,用于修改更新
     *
     * @param clazz    javabean的class
     * @param builders 条件构建器
     * @return
     * @see CriterionBuilder
     */
    <TBean> TBean[] queryBeansForUpdate(Class<TBean> clazz, CriterionBuilder... builders);

    /**
     * 通过sql条件加载指定的javabean,用于修改更新
     *
     * @param clazz    javabean的class
     * @param whereSql 条件sql,参数用?
     * @param args     参数
     * @return
     */
    <TBean> TBean[] queryBeansForUpdate(Class<TBean> clazz, String whereSql, Object... args);

    /**
     * 通过CriteriaBuilder组装条件，并查询单个javabean的部分字段
     *
     * @param clazz      javabean的class
     * @param loadFields 需要加载的字段集合,如果为空，默认加载Id、代码和名称字段
     * @param builders   条件构建器
     * @return
     */
    <TBean> TBean queryPartBean(Class<TBean> clazz, Collection<String> loadFields, CriterionBuilder... builders);

    /**
     * 通过sql条件加载指定的单个javabean的部分字段
     *
     * @param clazz      javabean的class
     * @param loadFields 需要加载的字段集合,如果为空，默认加载Id、代码和名称字段
     * @param whereSql   条件sql,参数用?
     * @param args       参数
     * @return
     */
    <TBean> TBean queryPartBean(Class<TBean> clazz, Collection<String> loadFields, String whereSql, Object... args);

    /**
     * 通过CriteriaBuilder组装条件，并查询单个javabean的部分字段，用于修改更新
     *
     * @param clazz      javabean的class
     * @param loadFields 需要加载的字段集合,如果为空，默认加载Id、代码和名称字段
     * @param builders   条件构建器
     * @return
     */
    <TBean> TBean queryPartBeanForUpdate(Class<TBean> clazz, Collection<String> loadFields,
                                         CriterionBuilder... builders);

    /**
     * 通过sql条件加载指定的单个javabean的部分字段,用于修改更新
     *
     * @param clazz      javabean的class
     * @param loadFields 需要加载的字段集合,如果为空，默认加载Id、代码和名称字段
     * @param whereSql   条件sql,参数用?
     * @param args       参数
     * @return
     */
    <TBean> TBean queryPartBeanForUpdate(Class<TBean> clazz, Collection<String> loadFields, String whereSql,
                                         Object... args);

    /**
     * 通过CriteriaBuilder组装条件，并查询javabean的部分字段
     *
     * @param clazz      javabean的class
     * @param loadFields 需要加载的字段集合,如果为空，默认加载Id、代码和名称字段
     * @param builders   条件构建器
     * @return
     */
    <TBean> TBean[] queryPartBeans(Class<TBean> clazz, Collection<String> loadFields, CriterionBuilder... builders);

    /**
     * 通过sql条件加载指定的javabean的部分字段
     *
     * @param clazz      javabean的class
     * @param loadFields 需要加载的字段集合,如果为空，默认加载Id、代码和名称字段
     * @param whereSql   条件sql,参数用?
     * @param args       参数
     * @return
     */
    <TBean> TBean[] queryPartBeans(Class<TBean> clazz, Collection<String> loadFields, String whereSql, Object... args);

    /**
     * 通过CriteriaBuilder组装条件，并查询javabean的部分字段，用于修改更新
     *
     * @param clazz      javabean的class
     * @param loadFields 需要加载的字段集合,如果为空，默认加载Id、代码和名称字段
     * @param builders   条件构建器
     * @return
     */
    <TBean> TBean[] queryPartBeansForUpdate(Class<TBean> clazz, Collection<String> loadFields,
                                            CriterionBuilder... builders);

    /**
     * 通过sql条件加载指定的javabean的部分字段,用于修改更新
     *
     * @param clazz      javabean的class
     * @param loadFields 需要加载的字段集合,如果为空，默认加载Id、代码和名称字段
     * @param whereSql   条件sql,参数用?
     * @param args       参数
     * @return
     */
    <TBean> TBean[] queryPartBeansForUpdate(Class<TBean> clazz, Collection<String> loadFields, String whereSql,
                                            Object... args);

    /**
     * 保存javabean
     *
     * @param clazz      对象元信息
     * @param dataObject 待保存的对象
     * @throws StaleObjectException
     */
    <TBean> void saveBean(Class<TBean> clazz, Object dataObject) throws StaleObjectException;

    /**
     * 批量保存javabean
     *
     * @param clazz
     * @param dataObjects
     * @throws StaleObjectException
     */
    <TBean> void saveBeans(Class<TBean> clazz, Object[] dataObjects) throws StaleObjectException;

}
